/**
 * 全局常量作为内部变量
 * 在 C++17 之前，以下是最简单且最常见的解决方案：
 *   1.创建一个头文件来保存这些常量
 *   2.在此头文件中，定义一个命名空间
 *   3.在命名空间内添加所有常量（确保它们是constexpr）
 *   4.在需要的地方包含头文件
 * 
 * 然后使用范围解析运算符 (::)，左侧为命名空间名称，右侧为变量名称，以便访问 .cpp 文件中的常量
 * 
 * 全局常量作为外部变量
 *   上述方法有一些潜在的缺点。
 *   虽然这很简单（对于较小的程序也很好），但每次constants.h被#included到不同的代码文件中时，每个变量都会被复制到包含的代码文件中。
 * 因此，如果 Constants.h 包含在 20 个不同的代码文件中，则每个变量都会重复 20 次。标头防护不会阻止这种情况发生，因为它们只能防止标头多次包含到单个包含文件中，而不是一次包含到多个不同的代码文件中。这带来了两个挑战：
 *   1.更改单个常量值需要重新编译包含常量标头的每个文件，这可能会导致大型项目的重建时间过长。
 *   2.如果常量很大并且无法优化掉，则可能会使用大量内存。
 * 避免这些问题的一种方法是将这些常量转换为外部变量，因为这样我们就可以拥有一个在所有文件之间共享的单个变量（初始化一次）。在此方法中，我们将在 .cpp 文件中定义常量（以确保定义仅存在于一个位置），并在标头中提出声明（将被其他文件包含）。
 * 
 * 在此方法中使用 const 而不是 constexpr，因为 constexpr 变量无法前向声明，即使它们具有外部链接也是如此。这是因为编译器需要在编译时知道变量的值，而前向声明不提供此信息。
 * 
 *   现在，符号常量将仅实例化一次（在 中constants.cpp），而不是在constants.h#included 的每个代码文件中实例化，
 * 并且这些常量的所有使用都将链接到在 中实例化的版本constants.cpp。对 所做的任何更改constants.cpp都只需要重新编译constants.cpp。
 *   然而，这种方法有一些缺点。首先，这些常量现在仅在它们实际定义于 ( ) 的文件中被视为编译时常量constants.cpp。在其他文件中，编译器只会看到前向声明，它不定义常量值（并且必须由链接器解析）。
 * 这意味着在其他文件中，这些被视为运行时常量值，而不是编译时常量。因此，在 之外constants.cpp，这些变量不能在需要编译时常量的任何地方使用。其次，由于编译时常量通常可以比运行时常量优化得更多，因此编译器可能无法对它们进行那么多优化。
 * 
 * inline 内联
 * constexpr 函数是隐式内联的，但 constexpr 变量不是隐式内联的。
 * 使用 inline 可以根据constants.h需要包含到任意多个代码文件中，但这些变量只会实例化一次并在所有代码文件之间共享。
 * 此方法确实保留了以下缺点：如果任何常量值发生更改，则需要重新编译包含常量标头的每个文件。
 * 
 * 
 */

#include "constants.h" // include a copy of each constant in this file
#include "constantsAnother.h"

#include <iostream>

int main()
{
    std::cout << "Enter a radius: ";
    double radius{};
    std::cin >> radius;

    std::cout << "1 The circumference is: " << 2 * radius * constants::pi << '\n';

    std::cout << "2 The circumference is: " << 2 * radius * constantsAnother::pi << '\n';

    return 0;
}